package com.cloud.common.config;

import com.cloud.common.annotation.WebInterceptor;
import com.cloud.common.context.AppContext;
import com.cloud.common.support.DefaultCorsFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Configuration
@ConditionalOnMissingClass("com.cloud.gateway.bean.GatewayInfo")
public class WebConfig implements WebMvcConfigurer {
    public static final String FROM_GATEWAY = "FromGateway";

    private void registryInterceptor(InterceptorRegistry registry) {
        Map<String, Object> map = AppContext.getBeansWithAnnotation(WebInterceptor.class);
        if (map.isEmpty()) {
            return;
        }
        // Pair<HandlerInterceptor, Order>
        List<Pair<HandlerInterceptor, Integer>> pairs = new ArrayList<>();
        map.forEach((key, value) -> {
            try {
                int order = value.getClass().getAnnotation(WebInterceptor.class).order();
                pairs.add(Pair.of((HandlerInterceptor) value, order));
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        });
        List<Pair<HandlerInterceptor, Integer>> list = pairs.stream().sorted(Comparator.comparing(Pair::getRight)).collect(Collectors.toList());
        for (Pair<HandlerInterceptor, Integer> pair : list) {
            log.info("registry interceptor " + pair.getLeft().getClass().getName());
            registry.addInterceptor(pair.getLeft()).order(pair.getRight());
        }
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registryInterceptor(registry);
    }

    @Bean
    public FilterRegistrationBean corsFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setName(DefaultCorsFilter.class.getSimpleName());
        registration.setFilter(new DefaultCorsFilter());
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
        registration.addUrlPatterns("/*");
        return registration;
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }
}
